package com.hdsx.netty.rpcclient.nio;

import com.hdsx.netty.protocol.BasicProtocol;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

/**
 * @author 占贤银
 * time 2024/8/10 13:41
 * description 生命之灯因热情而点燃，生命之舟因拼搏而前行
 */
public class NioProxy implements InvocationHandler {

    private int port;
    private String host;

    public NioProxy(int port, String host) {
        this.port = port;
        this.host = host;
    }

    public <T> T create(Class<T> aClazz){
        return (T) Proxy.newProxyInstance(aClazz.getClassLoader(), new Class[]{aClazz}, this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
    {
        BasicProtocol protocol = new BasicProtocol();
        protocol.setClassName(method.getDeclaringClass().getName());
        protocol.setMethodName(method.getName());
        protocol.setParameterType(method.getParameterTypes());
        protocol.setParameterValues(args);
        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.connect(new InetSocketAddress(this.host, this.port));
            //socketChannel.configureBlocking(false);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(protocol);
            System.out.println(protocol);
            socketChannel.write(ByteBuffer.wrap(baos.toByteArray()));
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            int len = socketChannel.read(byteBuffer);
            System.out.println("len = " + len);
            System.out.println(byteBuffer);
            byteBuffer.flip();
            ByteArrayInputStream bais = new ByteArrayInputStream(byteBuffer.array());
            ObjectInputStream ois = new ObjectInputStream(bais);
            Object result = ois.readObject();
            byteBuffer.clear();
            ois.close();
            bais.close();
            oos.close();
            baos.close();
            socketChannel.close();
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
